package meiyunting.shiwuzhaoling.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import meiyunting.shiwuzhaoling.service.ZipkinDemoService;

/**
 * 链路跟踪演示控制器
 * 用于演示Zipkin分布式链路跟踪功能
 */
@Slf4j
@RestController
@RequestMapping("/api/zipkin")
public class ZipkinDemoController {

    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private ZipkinDemoService zipkinDemoService;
    
    @Value("${server.port}")
    private String serverPort;
    
    /**
     * 简单的链路跟踪演示
     * @return 演示结果
     */
    @GetMapping("/simple")
    public Map<String, Object> simpleTrace() {
        log.info("进入简单链路跟踪演示接口");
        
        Map<String, Object> result = new HashMap<>();
        result.put("service", "lost-found-service");
        result.put("port", serverPort);
        result.put("timestamp", System.currentTimeMillis());
        result.put("message", "这是一个简单的链路跟踪演示");
        
        log.info("简单链路跟踪演示接口处理完成");
        return result;
    }
    
    /**
     * 复杂的链路跟踪演示，包含多个子调用
     * @return 演示结果
     */
    @GetMapping("/complex")
    public Map<String, Object> complexTrace() {
        log.info("进入复杂链路跟踪演示接口");
        
        // 模拟处理时间
        sleep(100);
        
        // 调用第一个子服务
        log.info("调用第一个子服务");
        Map<String, Object> service1Result = callSubService1();
        
        // 模拟处理时间
        sleep(50);
        
        // 调用第二个子服务
        log.info("调用第二个子服务");
        Map<String, Object> service2Result = callSubService2();
        
        // 组装最终结果
        Map<String, Object> result = new HashMap<>();
        result.put("service", "lost-found-service");
        result.put("port", serverPort);
        result.put("timestamp", System.currentTimeMillis());
        result.put("message", "这是一个复杂的链路跟踪演示");
        result.put("service1Result", service1Result);
        result.put("service2Result", service2Result);
        
        log.info("复杂链路跟踪演示接口处理完成");
        return result;
    }
    
    /**
     * 调用子服务1
     */
    private Map<String, Object> callSubService1() {
        log.info("子服务1处理开始");
        
        // 模拟处理时间
        sleep(200);
        
        Map<String, Object> result = new HashMap<>();
        result.put("name", "sub-service-1");
        result.put("timestamp", System.currentTimeMillis());
        result.put("data", "子服务1的数据");
        
        log.info("子服务1处理完成");
        return result;
    }
    
    /**
     * 调用子服务2
     */
    private Map<String, Object> callSubService2() {
        log.info("子服务2处理开始");
        
        // 模拟处理时间
        sleep(150);
        
        // 模拟调用外部服务
        try {
            log.info("子服务2调用外部服务");
            String url = "http://localhost:" + serverPort + "/api/zipkin/simple";
            restTemplate.getForObject(url, Map.class);
        } catch (Exception e) {
            log.error("调用外部服务失败", e);
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("name", "sub-service-2");
        result.put("timestamp", System.currentTimeMillis());
        result.put("data", "子服务2的数据");
        
        log.info("子服务2处理完成");
        return result;
    }
    
    /**
     * 模拟处理延时
     */
    private void sleep(long milliseconds) {
        try {
            TimeUnit.MILLISECONDS.sleep(milliseconds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 使用自定义Span演示
     * @param businessId 业务ID
     * @return 处理结果
     */
    @GetMapping("/custom-span/{businessId}")
    public Map<String, Object> customSpanDemo(@PathVariable String businessId) {
        log.info("进入自定义Span演示接口，业务ID: {}", businessId);
        
        Map<String, Object> result = zipkinDemoService.processWithCustomSpan(businessId);
        
        log.info("自定义Span演示接口处理完成");
        return result;
    }
} 